package asia.yuanding.wechat.web.netty;

import asia.yuanding.wechat.web.netty.handler.HttpRequestHandler;
import asia.yuanding.wechat.web.netty.handler.WebSocketFrameHandler;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.handler.stream.ChunkedWriteHandler;
import io.netty.handler.timeout.IdleStateHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;


import javax.annotation.PostConstruct;
import javax.annotation.Resource;

@Configuration
public class NettyStarter {

    private static final Logger logger = LoggerFactory.getLogger(NettyStarter.class);

    private final int port = 8889;

    @Resource
    private HttpRequestHandler httpRequestHandler;

     @Resource
    private WebSocketFrameHandler webSocketFrameHandler;

    @EventListener(ApplicationReadyEvent.class)
    public void onReady() {
        this.start();
    }

    @Async
    public void start() {
        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
        EventLoopGroup workerGroup = new NioEventLoopGroup();

        try {
            ServerBootstrap bootstrap = new ServerBootstrap();
            bootstrap.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel ch) {
                            ChannelPipeline pipeline = ch.pipeline();
                            // HTTP 编解码器
                            pipeline.addLast(new HttpServerCodec());
                            // 支持异步写大文件（用于处理文件传输）
                            pipeline.addLast(new ChunkedWriteHandler());
                            // 聚合 HTTP 消息，防止分片
                            pipeline.addLast(new HttpObjectAggregator(65536));

                            // 在 WebSocketServerProtocolHandler 之前加
                            pipeline.addLast(httpRequestHandler);

                            pipeline.addLast(new IdleStateHandler(100000000, 100000000, 0));

                            // 处理 WS 协议，路径必须和客户端保持一致，例如 "/ws"
                            pipeline.addLast(new WebSocketServerProtocolHandler("/ws" , "WebSocket" ,  true , 65536 * 10 , true , true));
                            // 你的业务 Handler，处理文本或二进制消息
                            pipeline.addLast(webSocketFrameHandler);
                        }
                    })
                    .option(ChannelOption.SO_BACKLOG, 128)
                    .childOption(ChannelOption.SO_KEEPALIVE, true);

            ChannelFuture future = bootstrap.bind(port).sync();
            logger.info("Netty WebSocket 服务启动，监听端口: {}", port);
            future.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            logger.error("Netty 服务启动被中断", e);
            Thread.currentThread().interrupt();
        } finally {
            workerGroup.shutdownGracefully();
            bossGroup.shutdownGracefully();
            logger.info("Netty 服务已关闭");
        }
    }
}
